/**
 * PerformanceMonitor - 性能监控和基准测试系统
 * 监控游戏性能指标，提供性能分析和优化建议
 * @class
 */

export interface PerformanceMetrics {
  /** 帧率（FPS） */
  fps: number
  /** 平均帧时间（毫秒） */
  averageFrameTime: number
  /** 最小帧时间（毫秒） */
  minFrameTime: number
  /** 最大帧时间（毫秒） */
  maxFrameTime: number
  /** 内存使用情况 */
  memoryUsage: MemoryInfo
  /** 渲染时间（毫秒） */
  renderTime: number
  /** 更新时间（毫秒） */
  updateTime: number
  /** 垃圾回收次数 */
  gcCount: number
}

export interface MemoryInfo {
  /** 已使用内存（MB） */
  usedJSHeapSize: number
  /** 总内存（MB） */
  totalJSHeapSize: number
  /** 内存限制（MB） */
  jsHeapSizeLimit: number
}

export interface PerformanceThresholds {
  /** 最低可接受FPS */
  minFPS: number
  /** 最大可接受帧时间（毫秒） */
  maxFrameTime: number
  /** 最大可接受内存使用（MB） */
  maxMemoryUsage: number
  /** 最大可接受渲染时间（毫秒） */
  maxRenderTime: number
}

export interface PerformanceAlert {
  /** 警告类型 */
  type: 'fps' | 'memory' | 'frameTime' | 'renderTime'
  /** 警告级别 */
  level: 'warning' | 'critical'
  /** 警告消息 */
  message: string
  /** 当前值 */
  currentValue: number
  /** 阈值 */
  threshold: number
  /** 时间戳 */
  timestamp: number
}

/**
 * 性能监控器类
 */
export class PerformanceMonitor {
  private frameTimeHistory: number[] = []
  private renderTimeHistory: number[] = []
  private updateTimeHistory: number[] = []
  private lastFrameTime: number = 0
  private frameCount: number = 0
  private startTime: number = 0
  private isMonitoring: boolean = false
  private historySize: number = 60 // 保存60帧的历史数据
  
  private thresholds: PerformanceThresholds = {
    minFPS: 30,
    maxFrameTime: 33.33, // ~30 FPS
    maxMemoryUsage: 100, // 100MB
    maxRenderTime: 16.67 // ~60 FPS
  }
  
  private alerts: PerformanceAlert[] = []
  private maxAlerts: number = 50
  
  // 基准测试相关
  private benchmarkResults: Map<string, number[]> = new Map()
  private currentBenchmark: string | null = null
  private benchmarkStartTime: number = 0

  /**
   * 创建性能监控器
   * @param thresholds - 性能阈值配置（可选）
   */
  constructor(thresholds?: Partial<PerformanceThresholds>) {
    if (thresholds) {
      this.thresholds = { ...this.thresholds, ...thresholds }
    }
    
    this.startTime = performance.now()
  }

  /**
   * 开始监控
   */
  startMonitoring(): void {
    this.isMonitoring = true
    this.startTime = performance.now()
    this.frameCount = 0
    this.lastFrameTime = performance.now()
  }

  /**
   * 停止监控
   */
  stopMonitoring(): void {
    this.isMonitoring = false
  }

  /**
   * 记录帧开始
   * @returns 帧开始时间戳
   */
  frameStart(): number {
    if (!this.isMonitoring) return 0
    
    const now = performance.now()
    
    // 计算帧时间
    if (this.lastFrameTime > 0) {
      const frameTime = now - this.lastFrameTime
      this.addFrameTime(frameTime)
    }
    
    this.lastFrameTime = now
    this.frameCount++
    
    return now
  }

  /**
   * 记录渲染开始
   * @returns 渲染开始时间戳
   */
  renderStart(): number {
    return performance.now()
  }

  /**
   * 记录渲染结束
   * @param startTime - 渲染开始时间戳
   */
  renderEnd(startTime: number): void {
    if (!this.isMonitoring || startTime === 0) return
    
    const renderTime = performance.now() - startTime
    this.addRenderTime(renderTime)
    
    // 检查渲染时间警告
    if (renderTime > this.thresholds.maxRenderTime) {
      this.addAlert({
        type: 'renderTime',
        level: renderTime > this.thresholds.maxRenderTime * 2 ? 'critical' : 'warning',
        message: `渲染时间过长: ${renderTime.toFixed(2)}ms`,
        currentValue: renderTime,
        threshold: this.thresholds.maxRenderTime,
        timestamp: Date.now()
      })
    }
  }

  /**
   * 记录更新开始
   * @returns 更新开始时间戳
   */
  updateStart(): number {
    return performance.now()
  }

  /**
   * 记录更新结束
   * @param startTime - 更新开始时间戳
   */
  updateEnd(startTime: number): void {
    if (!this.isMonitoring || startTime === 0) return
    
    const updateTime = performance.now() - startTime
    this.addUpdateTime(updateTime)
  }

  /**
   * 添加帧时间到历史记录
   * @param frameTime - 帧时间
   */
  private addFrameTime(frameTime: number): void {
    this.frameTimeHistory.push(frameTime)
    
    if (this.frameTimeHistory.length > this.historySize) {
      this.frameTimeHistory.shift()
    }
    
    // 检查帧时间警告
    if (frameTime > this.thresholds.maxFrameTime) {
      const fps = 1000 / frameTime
      this.addAlert({
        type: 'frameTime',
        level: frameTime > this.thresholds.maxFrameTime * 2 ? 'critical' : 'warning',
        message: `帧时间过长: ${frameTime.toFixed(2)}ms (${fps.toFixed(1)} FPS)`,
        currentValue: frameTime,
        threshold: this.thresholds.maxFrameTime,
        timestamp: Date.now()
      })
    }
  }

  /**
   * 添加渲染时间到历史记录
   * @param renderTime - 渲染时间
   */
  private addRenderTime(renderTime: number): void {
    this.renderTimeHistory.push(renderTime)
    
    if (this.renderTimeHistory.length > this.historySize) {
      this.renderTimeHistory.shift()
    }
  }

  /**
   * 添加更新时间到历史记录
   * @param updateTime - 更新时间
   */
  private addUpdateTime(updateTime: number): void {
    this.updateTimeHistory.push(updateTime)
    
    if (this.updateTimeHistory.length > this.historySize) {
      this.updateTimeHistory.shift()
    }
  }

  /**
   * 获取当前性能指标
   * @returns 性能指标对象
   */
  getMetrics(): PerformanceMetrics {
    const now = performance.now()
    const elapsedTime = now - this.startTime
    const fps = this.frameCount > 0 ? (this.frameCount / elapsedTime) * 1000 : 0
    
    const averageFrameTime = this.getAverage(this.frameTimeHistory)
    const minFrameTime = Math.min(...this.frameTimeHistory) || 0
    const maxFrameTime = Math.max(...this.frameTimeHistory) || 0
    
    const renderTime = this.getAverage(this.renderTimeHistory)
    const updateTime = this.getAverage(this.updateTimeHistory)
    
    return {
      fps: Math.round(fps * 100) / 100,
      averageFrameTime: Math.round(averageFrameTime * 100) / 100,
      minFrameTime: Math.round(minFrameTime * 100) / 100,
      maxFrameTime: Math.round(maxFrameTime * 100) / 100,
      memoryUsage: this.getMemoryInfo(),
      renderTime: Math.round(renderTime * 100) / 100,
      updateTime: Math.round(updateTime * 100) / 100,
      gcCount: this.getGCCount()
    }
  }

  /**
   * 获取内存使用信息
   * @returns 内存信息对象
   */
  private getMemoryInfo(): MemoryInfo {
    if ('memory' in performance) {
      const memory = (performance as any).memory
      return {
        usedJSHeapSize: Math.round(memory.usedJSHeapSize / 1024 / 1024 * 100) / 100,
        totalJSHeapSize: Math.round(memory.totalJSHeapSize / 1024 / 1024 * 100) / 100,
        jsHeapSizeLimit: Math.round(memory.jsHeapSizeLimit / 1024 / 1024 * 100) / 100
      }
    }
    
    return {
      usedJSHeapSize: 0,
      totalJSHeapSize: 0,
      jsHeapSizeLimit: 0
    }
  }

  /**
   * 获取垃圾回收次数（估算）
   * @returns GC次数
   */
  private getGCCount(): number {
    // 这是一个简化的估算，实际GC次数很难准确获取
    const memoryInfo = this.getMemoryInfo()
    return Math.floor(memoryInfo.usedJSHeapSize / 10) // 粗略估算
  }

  /**
   * 计算数组平均值
   * @param values - 数值数组
   * @returns 平均值
   */
  private getAverage(values: number[]): number {
    if (values.length === 0) return 0
    return values.reduce((sum, value) => sum + value, 0) / values.length
  }

  /**
   * 添加性能警告
   * @param alert - 警告对象
   */
  private addAlert(alert: PerformanceAlert): void {
    this.alerts.push(alert)
    
    if (this.alerts.length > this.maxAlerts) {
      this.alerts.shift()
    }
    
    // 在控制台输出警告
    const level = alert.level === 'critical' ? 'error' : 'warn'
    console[level](`[性能警告] ${alert.message}`)
  }

  /**
   * 获取所有警告
   * @returns 警告数组
   */
  getAlerts(): PerformanceAlert[] {
    return [...this.alerts]
  }

  /**
   * 获取最近的警告
   * @param count - 要获取的警告数量
   * @returns 最近的警告数组
   */
  getRecentAlerts(count: number = 10): PerformanceAlert[] {
    return this.alerts.slice(-count)
  }

  /**
   * 清除所有警告
   */
  clearAlerts(): void {
    this.alerts.length = 0
  }

  /**
   * 设置性能阈值
   * @param thresholds - 新的阈值配置
   */
  setThresholds(thresholds: Partial<PerformanceThresholds>): void {
    this.thresholds = { ...this.thresholds, ...thresholds }
  }

  /**
   * 获取当前阈值配置
   * @returns 阈值配置对象
   */
  getThresholds(): PerformanceThresholds {
    return { ...this.thresholds }
  }

  /**
   * 开始基准测试
   * @param name - 基准测试名称
   */
  startBenchmark(name: string): void {
    this.currentBenchmark = name
    this.benchmarkStartTime = performance.now()
  }

  /**
   * 结束基准测试
   * @returns 基准测试耗时（毫秒）
   */
  endBenchmark(): number {
    if (!this.currentBenchmark) {
      console.warn('没有正在进行的基准测试')
      return 0
    }
    
    const duration = performance.now() - this.benchmarkStartTime
    
    if (!this.benchmarkResults.has(this.currentBenchmark)) {
      this.benchmarkResults.set(this.currentBenchmark, [])
    }
    
    this.benchmarkResults.get(this.currentBenchmark)!.push(duration)
    this.currentBenchmark = null
    
    return duration
  }

  /**
   * 获取基准测试结果
   * @param name - 基准测试名称
   * @returns 基准测试统计信息
   */
  getBenchmarkResults(name: string): {
    count: number
    average: number
    min: number
    max: number
    total: number
  } | null {
    const results = this.benchmarkResults.get(name)
    if (!results || results.length === 0) {
      return null
    }
    
    const total = results.reduce((sum, time) => sum + time, 0)
    const average = total / results.length
    const min = Math.min(...results)
    const max = Math.max(...results)
    
    return {
      count: results.length,
      average: Math.round(average * 100) / 100,
      min: Math.round(min * 100) / 100,
      max: Math.round(max * 100) / 100,
      total: Math.round(total * 100) / 100
    }
  }

  /**
   * 获取所有基准测试结果
   * @returns 所有基准测试结果的映射
   */
  getAllBenchmarkResults(): Record<string, any> {
    const results: Record<string, any> = {}
    
    for (const [name] of this.benchmarkResults) {
      results[name] = this.getBenchmarkResults(name)
    }
    
    return results
  }

  /**
   * 清除基准测试结果
   * @param name - 要清除的基准测试名称（可选，不提供则清除所有）
   */
  clearBenchmarkResults(name?: string): void {
    if (name) {
      this.benchmarkResults.delete(name)
    } else {
      this.benchmarkResults.clear()
    }
  }

  /**
   * 生成性能报告
   * @returns 详细的性能报告字符串
   */
  generateReport(): string {
    const metrics = this.getMetrics()
    const alerts = this.getRecentAlerts(5)
    const benchmarks = this.getAllBenchmarkResults()
    
    let report = '=== 性能监控报告 ===\n\n'
    
    // 基本指标
    report += '基本性能指标:\n'
    report += `  FPS: ${metrics.fps}\n`
    report += `  平均帧时间: ${metrics.averageFrameTime}ms\n`
    report += `  最小帧时间: ${metrics.minFrameTime}ms\n`
    report += `  最大帧时间: ${metrics.maxFrameTime}ms\n`
    report += `  渲染时间: ${metrics.renderTime}ms\n`
    report += `  更新时间: ${metrics.updateTime}ms\n\n`
    
    // 内存使用
    report += '内存使用情况:\n'
    report += `  已使用: ${metrics.memoryUsage.usedJSHeapSize}MB\n`
    report += `  总内存: ${metrics.memoryUsage.totalJSHeapSize}MB\n`
    report += `  内存限制: ${metrics.memoryUsage.jsHeapSizeLimit}MB\n\n`
    
    // 最近警告
    if (alerts.length > 0) {
      report += '最近警告:\n'
      alerts.forEach(alert => {
        report += `  [${alert.level.toUpperCase()}] ${alert.message}\n`
      })
      report += '\n'
    }
    
    // 基准测试结果
    if (Object.keys(benchmarks).length > 0) {
      report += '基准测试结果:\n'
      for (const [name, result] of Object.entries(benchmarks)) {
        if (result) {
          report += `  ${name}: 平均 ${result.average}ms (${result.count} 次测试)\n`
        }
      }
    }
    
    return report
  }

  /**
   * 重置所有统计数据
   */
  reset(): void {
    this.frameTimeHistory.length = 0
    this.renderTimeHistory.length = 0
    this.updateTimeHistory.length = 0
    this.frameCount = 0
    this.startTime = performance.now()
    this.lastFrameTime = 0
    this.clearAlerts()
    this.clearBenchmarkResults()
  }

  /**
   * 检查当前性能是否健康
   * @returns 性能健康状态
   */
  isPerformanceHealthy(): {
    healthy: boolean
    issues: string[]
  } {
    const metrics = this.getMetrics()
    const issues: string[] = []
    
    if (metrics.fps < this.thresholds.minFPS) {
      issues.push(`FPS过低: ${metrics.fps} < ${this.thresholds.minFPS}`)
    }
    
    if (metrics.averageFrameTime > this.thresholds.maxFrameTime) {
      issues.push(`帧时间过长: ${metrics.averageFrameTime}ms > ${this.thresholds.maxFrameTime}ms`)
    }
    
    if (metrics.memoryUsage.usedJSHeapSize > this.thresholds.maxMemoryUsage) {
      issues.push(`内存使用过高: ${metrics.memoryUsage.usedJSHeapSize}MB > ${this.thresholds.maxMemoryUsage}MB`)
    }
    
    if (metrics.renderTime > this.thresholds.maxRenderTime) {
      issues.push(`渲染时间过长: ${metrics.renderTime}ms > ${this.thresholds.maxRenderTime}ms`)
    }
    
    return {
      healthy: issues.length === 0,
      issues
    }
  }
}